package net.goutalk.glcs.module.oa.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.EnabledMark;
import net.goutalk.glcs.common.model.result.R;
import net.goutalk.glcs.common.page.ConventPage;
import net.goutalk.glcs.common.page.PageOutput;
import net.goutalk.glcs.common.utils.VoToColumnUtil;
import net.goutalk.glcs.module.oa.dto.AddNewsDto;
import net.goutalk.glcs.module.oa.dto.NewsPageDto;
import net.goutalk.glcs.module.oa.entity.News;
import net.goutalk.glcs.module.oa.entity.NewsRelation;
import net.goutalk.glcs.module.oa.service.INewsRelationService;
import net.goutalk.glcs.module.oa.service.INewsService;
import net.goutalk.glcs.module.oa.vo.NewsPageVo;
import net.goutalk.glcs.module.oa.vo.NewsVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 新闻中心表 前端控制器
 * </p>
 *
 * @author zlf
 * @since 2022-06-16
 */
@RestController
@RequestMapping(GlobalConstant.OA_MODULE_PREFIX + "/news")
@Api(value = GlobalConstant.OA_MODULE_PREFIX + "/news", tags = "新闻公告")
@AllArgsConstructor
public class NewsController {

    private INewsService newsService;

    private INewsRelationService newsRelationService;


    @GetMapping
    @ApiOperation(value = "获取新闻分页")
    public R page(NewsPageDto dto) {
        Wrapper<News> wrapper = Wrappers.<News>query().lambda()
                .eq(News::getTypeId, dto.getType())
                .like(StrUtil.isNotBlank(dto.getKeyword()), News::getFullHead, dto.getKeyword())
                .select(News.class, x -> VoToColumnUtil.fieldsToColumns(NewsPageVo.class).contains(x.getProperty()));
        IPage<News> page = newsService.page(ConventPage.getPage(dto), wrapper);
        PageOutput<NewsPageVo> pageOutput = ConventPage.getPageOutput(page, NewsPageVo.class);
        return R.ok(pageOutput);
    }

    @GetMapping("/box")
    @ApiOperation(value = "获取新闻分页")
    public R box(NewsPageDto dto) {
        MPJLambdaWrapper<News> wrapper = MPJWrappers.<News>lambdaJoin()
                .distinct()
                .eq(News::getTypeId, dto.getType())
                .like(StrUtil.isNotBlank(dto.getKeyword()), News::getFullHead, dto.getKeyword())
                .leftJoin(NewsRelation.class, onWrapper -> onWrapper.eq(NewsRelation::getNewsId, News::getId).eq(NewsRelation::getUserId, StpUtil.getLoginIdAsLong()))
                .selectAs(NewsRelation::getId, NewsPageVo::getReadId)
                .selectAs(News::getId, NewsPageVo::getId)
                .select(News.class, x -> VoToColumnUtil.fieldsToColumns(NewsPageVo.class).contains(x.getProperty()));
        IPage<NewsPageVo> page = newsService.selectJoinListPage(ConventPage.getPage(dto), NewsPageVo.class, wrapper);
        PageOutput<NewsPageVo> pageOutput = ConventPage.getPageOutput(page, NewsPageVo.class);
        return R.ok(pageOutput);
    }

    @PostMapping
    @ApiOperation(value = "新增新闻")
    public R add(@RequestBody AddNewsDto addNewsDto) {
        News news = BeanUtil.toBean(addNewsDto, News.class);
        news.setEnabledMark(EnabledMark.DISABLED.getCode());
        return R.ok(newsService.save(news));
    }

    @GetMapping(value = "/info")
    @ApiOperation(value = "新闻详情")
    public R info(@RequestParam Long id, @RequestParam(required = false) Boolean isRead) {
        News news = newsService.getById(id);
        if (news == null) {
            R.error("找不到此新闻！");
        }
        if (BooleanUtils.isTrue(isRead)) {
            NewsRelation newsRelation = new NewsRelation();
            newsRelation.setNewsId(id);
            newsRelation.setUserId(StpUtil.getLoginIdAsLong());
            newsRelationService.remove(Wrappers.<NewsRelation>query().lambda()
                    .eq(NewsRelation::getUserId, StpUtil.getLoginIdAsLong())
                    .eq(NewsRelation::getNewsId, id));
            newsRelationService.save(newsRelation);
        }
        return R.ok(BeanUtil.toBean(news, NewsVo.class));
    }

    @PutMapping
    @ApiOperation(value = "修改新闻")
    public R update(@RequestBody AddNewsDto addNewsDto) {
        News news = BeanUtil.toBean(addNewsDto, News.class);
        return R.ok(newsService.updateById(news));
    }

    @DeleteMapping
    @ApiOperation(value = "删除新闻")
    public R delete(@RequestBody List<Long> ids) {
        return R.ok(newsService.delete(ids));
    }


    @PutMapping("/change-status")
    @ApiOperation(value = "发布或下架新闻")
    public R changeStatus(@RequestParam("id") String id, @RequestParam("type") Integer type) throws Exception {
        News glcsNews = newsService.getById(id);
        if (type == null || glcsNews == null) {
            throw new Exception("参数异常");
        }
        if (type.equals(glcsNews.getEnabledMark())) {
            if (type == 1) {
                throw new Exception("新闻已发布!!!");
            } else if (type == 0) {
                throw new Exception("新闻已下架!!!");
            }
        }
        glcsNews.setEnabledMark(type);
        return R.ok(newsService.updateById(glcsNews));
    }

    @PutMapping("/read")
    @ApiOperation(value = "读新闻")
    public R read(@RequestBody List<Long> ids) {
        List<NewsRelation> toSaveList = new ArrayList<>();
        for (Long id : ids) {
            NewsRelation newsRelation = new NewsRelation();
            newsRelation.setUserId(StpUtil.getLoginIdAsLong());
            newsRelation.setNewsId(id);
            toSaveList.add(newsRelation);
        }
        newsRelationService.remove(Wrappers.<NewsRelation>query().lambda()
                .in(NewsRelation::getNewsId, ids)
                .eq(NewsRelation::getUserId, StpUtil.getLoginIdAsLong()));
        return R.ok(newsRelationService.saveBatch(toSaveList));
    }
}
